#ifndef SCREEN_H
#define SCREEN_H

#include "common.h"

#include <stdbool.h>
#include <SDL2/SDL.h>
#include <libavformat/avformat.h>

#include "controller.h"
#include "coords.h"
#include "display.h"
#include "fps_counter.h"
#include "frame_buffer.h"
#include "input_manager.h"
#include "opengl.h"
#include "options.h"
#include "trait/key_processor.h"
#include "trait/frame_sink.h"
#include "trait/mouse_processor.h"

/*
自定义屏幕上下文
*/
struct sc_screen {
    struct sc_frame_sink frame_sink; // frame sink trait

#ifndef NDEBUG
    bool open; // track the open/close state to assert correct behavior
#endif

    bool video;

    struct sc_display display;

     // 输入管理器
    struct sc_input_manager im;
    struct sc_frame_buffer fb;
    struct sc_fps_counter fps_counter;

    // The initial requested window properties 对窗体的初始要求，来自于命令行
    struct {
        int16_t x;
        int16_t y;
        // 头文件 <stdint.h>
        uint16_t width;
        uint16_t height;
        bool fullscreen;
        bool start_fps_counter;
    } req;

    SDL_Window *window;

    // 最新的视频帧的分辨率信息。从android设备中初始化屏幕的分辨率，作为视频帧的尺寸
    struct sc_size frame_size;
    struct sc_size content_size; // rotated frame_size 仅表示显示内容的分辨率，不指明旋转方向

// 从全屏或最大化恢复原始窗体时用到
    bool resize_pending; // resize requested while fullscreen or maximized
    // The content size the last time the window was not maximized or
    // fullscreen (meaningful only when resize_pending is true)
    struct sc_size windowed_content_size;

// 屏幕旋转方向 client rotation: 0, 1, 2 or 3 (x90 degrees counterclockwise 逆时针旋转)
    // client orientation
    enum sc_orientation orientation;
    // rectangle of the content (excluding black borders)
    struct SDL_Rect rect;

    // 是否有视频帧，初始化时为false,有服务端的视频帧传入时将永久改为true
    bool has_frame;

    // 当前是否为全屏模式，默认值false
    bool fullscreen;

     // 当前是否为最大化窗口
    bool maximized;
    bool minimized;

    // To enable/disable mouse capture, a mouse capture key (LALT, LGUI or
    // RGUI) must be pressed. This variable tracks the pressed capture key.
    SDL_Keycode mouse_capture_key_pressed;

// 当前数据帧
    AVFrame *frame;

    bool paused;
    AVFrame *resume_frame;
};

/* 自定义屏幕参数，仅用于screen初始化 */
struct sc_screen_params {
    bool video;

    struct sc_controller *controller;
    struct sc_file_pusher *fp;

    // 键盘事件处理器上下文，根据不同模式进行加载
    struct sc_key_processor *kp;

    // 鼠标事件处理器上下文，根据不同模式进行加载
    struct sc_mouse_processor *mp;
    struct sc_gamepad_processor *gp;

    struct sc_mouse_bindings mouse_bindings;
    bool legacy_paste;
    bool clipboard_autosync;

    // 自定义热键启动键
    uint8_t shortcut_mods; // OR of enum sc_shortcut_mod values

    // 窗体名称，或从命令行设置，或者是设备的名称
    const char *window_title;

    // PC客户端窗体是否在最上层，默认false
    bool always_on_top;
    // PC窗体位置的初始X坐标 accepts SC_WINDOW_POSITION_UNDEFINED
    int16_t window_x; 
    // PC窗体位置的初始Y坐标 accepts SC_WINDOW_POSITION_UNDEFINED
    int16_t window_y;
    // PC窗体的初始宽度
    uint16_t window_width;
    // PC窗体的初始高度
    uint16_t window_height;
    // PC窗体是否为无边框模式
    bool window_borderless;
    // 屏幕旋转方向
    enum sc_orientation orientation;
    
    bool mipmaps;
    // PC客户端窗体全屏显示，默认值是false
    bool fullscreen;
    bool start_fps_counter;
};

// initialize screen, create window, renderer and texture (window is hidden)
// @param screen 屏幕上下文
// @param params 屏幕初始化参数
// \return 成功返回true,否则返回false
bool
sc_screen_init(struct sc_screen *screen, const struct sc_screen_params *params);

// request to interrupt any inner thread
// must be called before screen_join()
void
sc_screen_interrupt(struct sc_screen *screen);

// join any inner thread
void
sc_screen_join(struct sc_screen *screen);

// destroy window, renderer and texture (if any) 回收屏幕窗体相关的资源
void
sc_screen_destroy(struct sc_screen *screen);

// hide the window 隐藏窗体
//
// It is used to hide the window immediately on closing without waiting for
// screen_destroy()
void
sc_screen_hide_window(struct sc_screen *screen);

// switch the fullscreen mode 切换全屏模式开关
void
sc_screen_switch_fullscreen(struct sc_screen *screen);

// resize window to optimal size (remove black borders)
void
sc_screen_resize_to_fit(struct sc_screen *screen);

// resize window to 1:1 (pixel-perfect) 恢复窗体原始比例
void
sc_screen_resize_to_pixel_perfect(struct sc_screen *screen);

// set the display orientation
// 设置屏幕旋转方向 0不旋转 1逆时针转90度，依次类推
// @param screen 屏幕上下文
// @param rotation 旋转方向的枚举
void
sc_screen_set_orientation(struct sc_screen *screen,
                          enum sc_orientation orientation);

// set the display pause state
void
sc_screen_set_paused(struct sc_screen *screen, bool paused);

// react to SDL events。屏幕事件处理
// @param screen 屏幕上下文
// @param event SDL2任意事件
// If this function returns false, scrcpy must exit with an error.
bool
sc_screen_handle_event(struct sc_screen *screen, const SDL_Event *event);

// convert point from window coordinates to frame coordinates
// x and y are expressed in pixels
// @param screen 屏幕上下文
// @param x SDL中的X坐标
// @param y SDL中的Y坐标
// @return 视频帧中的坐标
struct sc_point
sc_screen_convert_window_to_frame_coords(struct sc_screen *screen,
                                        int32_t x, int32_t y);

// convert point from drawable coordinates to frame coordinates
// x and y are expressed in pixels
struct sc_point
sc_screen_convert_drawable_to_frame_coords(struct sc_screen *screen,
                                          int32_t x, int32_t y);

// Convert coordinates from window to drawable.
// Events are expressed in window coordinates, but content is expressed in
// drawable coordinates. They are the same if HiDPI scaling is 1, but differ
// otherwise.
void
sc_screen_hidpi_scale_coords(struct sc_screen *screen, int32_t *x, int32_t *y);

#endif
